﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Base.Schema;

namespace Base.DataModel
{
    public enum FieldType
    {
        Single,
        Multi
    }

    [SchemaElementName("field")]
    public class Field : IdentifiedItem
    {
        // C'tors ////
        public Field(string name, Guid64 id, FieldType type, params Fieldlet[] fieldlets)
            : base(name, id)
        {
            Type = type;

            _fieldlets = new IdItemCollection<Fieldlet>(this);
            if (fieldlets != null)
            {
                foreach (Fieldlet f in fieldlets)
                {
                    _fieldlets.Add(f);
                }
            }
        }

        public Field(string name, FieldType type, params Fieldlet[] fieldlets)
            : this(name, null, type, fieldlets)
        { }

        public Field(string name, params Fieldlet[] fieldlets)
            : this(name, null, FieldType.Single, fieldlets)
        { }
        
        public Field(string name, Guid64 id)
            : this(name, id, FieldType.Single, null) 
        { }

        public Field(string name)
            : this(name, null, FieldType.Single, null)
        { }

        // Containers ////
        private IdItemCollection<Fieldlet> _fieldlets;

        [SchemaCollection("fieldlets")]
        public IdItemCollection<Fieldlet> Fieldlets
        {
            get
            {
                return this._fieldlets;
            }
        }

        [SchemaCollection("duplications")]
        public Duplication[] Duplications
        {
            get
            {
                List<Duplication> dups = new List<Duplication>();

                foreach (Field targetField in _targets.Values)
                {
                    dups.Add(new Duplication((Entity)targetField.Parent, targetField));
                }

                return dups.ToArray();
            }
        }

        // Preferences ////
        [SchemaPreference("type")]
        public FieldType Type { get; set; }

        // Duplication ////
        private Dictionary<Guid64, Field> _targets = new Dictionary<Guid64,Field>();

        public Field GetDuplicateField(Entity target)
        {
            Field res;
            if (_targets.TryGetValue(target.Id, out res))
            {
                return res;
            }

            Entity p = (Entity)Parent;
            throw new KeyNotFoundException(
                String.Format("Field <{0} {1}>.<{2} {3}> does not have " +
                              "a duplicate in the <{4} {5}> entity.",
                              p.Name, p.Id, Name, Id, target.Name, target.Id));
        }

        public void DuplicateToField(Entity target, Field targetField)
        {
            // Duplicate this link with the target field in the target entity
            _targets[target.Id] = targetField;
            targetField._targets[((Entity)this.Parent).Id] = this;
        }

        // Static Helpers ////
        public static Field SingleFieldlet(Fieldlet f)
        {
            Field res = new Field(f.Name);
            res.Fieldlets.Add(f);

            return res;
        }
    }

    public class MultiField : Field
    {
        public MultiField(string name, params Fieldlet[] fieldlets)
            : base(name, FieldType.Multi, fieldlets)
        { }
    }
}
